namespace ITU.EtermCore
{
    using System;
    using System.Globalization;
    using System.Text.RegularExpressions;

    public abstract class Packet
    {
        private EtermConnection.CmdResultCB cb;
        private int cmdid;
        private string cmdstring;
        private EtermConnection ecchannel;
        private byte[] encodesendb;
        private CmdResultEvaluator evaluator;
        private bool is3in1;
        private bool issendbyte;
        private object remoteobject;
        private bool repeat;
        private byte[] sendb;
        private int sendblength;
        private CmdPacket subcmdpacket;
        private int uscid;

        public Packet(string cmdstring)
        {
            this.encodesendb = null;
            this.cmdstring = "";
            this.cb = null;
            this.subcmdpacket = null;
            this.evaluator = null;
            this.repeat = false;
            this.issendbyte = false;
            this.is3in1 = false;
            this.ecchannel = null;
            this.remoteobject = null;
            this.cmdstring = this.FormatMultiCmdLine(cmdstring);
        }

        public Packet(byte[] b, EtermConnection.CmdResultCB cb)
        {
            this.encodesendb = null;
            this.cmdstring = "";
            this.cb = null;
            this.subcmdpacket = null;
            this.evaluator = null;
            this.repeat = false;
            this.issendbyte = false;
            this.is3in1 = false;
            this.ecchannel = null;
            this.remoteobject = null;
            this.IsSendByte = true;
            try
            {
                int count = 0;
                if (b.Length > 20)
                {
                    for (int i = 0x13; i < (b.Length - 1); i++)
                    {
                        if ((b[i] == 0x20) && (b[i + 1] == 3))
                        {
                            count = i + 2;
                            break;
                        }
                    }
                }
                if (count <= 0x15)
                {
                    throw new Exception("构造443包出错,具体原因:包长度不够,或者没有结尾标识");
                }
                this.sendb = new byte[count];
                Buffer.BlockCopy(b, 0, this.sendb, 0, count);
                this.sendblength = count;
                this.encodesendb = this.sendb;
            }
            catch (Exception exception)
            {
                throw new Exception(string.Concat(new object[] { "构造443包出错,具体原因:", exception.Message, exception.TargetSite, exception.Source }));
            }
        }

        public Packet(byte[] b, int length)
        {
            this.encodesendb = null;
            this.cmdstring = "";
            this.cb = null;
            this.subcmdpacket = null;
            this.evaluator = null;
            this.repeat = false;
            this.issendbyte = false;
            this.is3in1 = false;
            this.ecchannel = null;
            this.remoteobject = null;
            this.sendb = new byte[length];
            Buffer.BlockCopy(b, 0, this.sendb, 0, length);
            this.sendblength = length;
            this.encodesendb = this.sendb;
        }

        public Packet(byte[] b, bool is3in1, EtermConnection.CmdResultCB cb)
        {
            this.encodesendb = null;
            this.cmdstring = "";
            this.cb = null;
            this.subcmdpacket = null;
            this.evaluator = null;
            this.repeat = false;
            this.issendbyte = false;
            this.is3in1 = false;
            this.ecchannel = null;
            this.remoteobject = null;
            int count = 0;
            for (int i = 0; i < (b.Length - 1); i++)
            {
                if ((b[i] == 0x7d) && (b[i + 1] == 3))
                {
                    count = i + 2;
                    break;
                }
            }
            this.sendb = new byte[count];
            Buffer.BlockCopy(b, 0, this.sendb, 0, count);
            this.sendblength = count;
            this.encodesendb = this.sendb;
        }

        public Packet(byte[] b, int length, EtermConnection.CmdResultCB cb) : this(b, length)
        {
            this.cb = cb;
        }

        internal abstract void bulidpacket();
        private string FormatMultiCmdLine(string s)
        {
            return Regex.Replace(s.Replace("\n", ""), "\r{1,3}", "\r");
        }

        public string GetAvhdate()
        {
            Match match = new Regex(@"([0-9]{1,2}[A-Za-z]{3}|\+)").Match(this.CmdString);
            if (match.Success)
            {
                if (match.Groups[1].ToString().Trim() == "+")
                {
                    return DateTime.Now.AddDays(1.0).ToString("ddMMM", new CultureInfo("en-US")).ToUpper();
                }
                return match.Groups[1].ToString().Trim().ToUpper();
            }
            return DateTime.Now.ToString("ddMMM", new CultureInfo("en-US")).ToUpper();
        }

        public void Send()
        {
            if ((this.EcChannel == null) || (this.EcChannel.m_ConnectionState != StateClass.ConnectionState.Logined))
            {
                throw new Exception("发送指令前需要先设置EcChannel，并处于连接状态");
            }
            this.bulidpacket();
            this.EcChannel.SendCmd(this);
        }

        public EtermConnection.CmdResultCB CB
        {
            get
            {
                return this.cb;
            }
            set
            {
                this.cb = value;
            }
        }

        public byte[] CmdBytes
        {
            get
            {
                return this.sendb;
            }
            set
            {
                this.sendb = value;
            }
        }

        public int CmdBytesLength
        {
            get
            {
                return this.sendblength;
            }
        }

        public int CmdId
        {
            get
            {
                return this.cmdid;
            }
            set
            {
                this.cmdid = value;
            }
        }

        public string CmdString
        {
            get
            {
                return this.cmdstring;
            }
        }

        public EtermConnection EcChannel
        {
            get
            {
                try
                {
                    return this.ecchannel;
                }
                catch
                {
                    return null;
                }
            }
            set
            {
                this.ecchannel = value;
                for (Packet packet = this.SubCmdPacket; packet != null; packet = packet.SubCmdPacket)
                {
                    packet.EcChannel = this.ecchannel;
                }
            }
        }

        internal byte[] EncodeCmdBytes
        {
            get
            {
                if (this.encodesendb == null)
                {
                    this.bulidpacket();
                }
                return this.encodesendb;
            }
            set
            {
                this.encodesendb = value;
                this.sendblength = this.encodesendb.Length;
            }
        }

        public CmdResultEvaluator Evaluator
        {
            get
            {
                return this.evaluator;
            }
            set
            {
                this.evaluator = value;
            }
        }

        public bool Is3In1
        {
            get
            {
                return this.is3in1;
            }
            set
            {
                this.is3in1 = value;
            }
        }

        public bool IsSendByte
        {
            get
            {
                return this.issendbyte;
            }
            set
            {
                this.issendbyte = value;
            }
        }

        public object RemoteObject
        {
            get
            {
                return this.remoteobject;
            }
            set
            {
                this.remoteobject = value;
            }
        }

        public bool Repeat
        {
            get
            {
                return this.repeat;
            }
            set
            {
                this.repeat = value;
            }
        }

        public CmdPacket SubCmdPacket
        {
            get
            {
                return this.subcmdpacket;
            }
            set
            {
                this.subcmdpacket = value;
            }
        }

        public int UscId
        {
            get
            {
                return this.uscid;
            }
            set
            {
                this.uscid = value;
            }
        }
    }
}
